package com.suyang.syt.util;

import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.suyang.syt.context.BeanFactoryContext;
import com.suyang.syt.model.dto.baidumap.Point;

public class AppUtil {
	private static final String LOGO_PATH = "/css/images/";
	private static final String PXJG_LOGO = "logo_px.png";
	private static final String TEACHER_LOGO = "logo_js.png";
	private static final String COURSE_LOGO = "logo_kc.png";
	private static final String COURSE_TYPE_LOGO = "logo_px.png";
	private static final String CHILDRENSTAR_LOGO = "logo_px.png";
	private static final String USER_LOGO = "logo_px.png";
	private static final String JXT_LOGO = "logo_px.png";
	private static final double EARTH_RADIUS = 6378137;
	private static final String CODE = "tongqutang.app.cn";

	private AppUtil() {
	}

	/** 根据APP传过来的时间值生成加密sn,确保安全性 */
	public static String getSn(String time) throws Exception {
		return Md5Util.md5(CODE, DateFormat.dateToString(new Date(Long.parseLong(time))));
	}

	public static String validateSn(HttpServletRequest request) throws Exception {
		if (request != null) {
			String sn = request.getParameter("sn");
			String time = request.getParameter("time");
			if (EmptyUtil.isNotEmpty(sn) && EmptyUtil.isNotEmpty(time)) {
				long timeMillis = Long.parseLong(time);
				long currentTimeMillis = System.currentTimeMillis();
				if (timeMillis - 90000 <= currentTimeMillis && currentTimeMillis <= timeMillis + 91000) {
					// 三分钟内有效
					if (sn.equals(getSn(time))) {
						// sn比对成功
						return "验证成功";
					}
				} else {
					return "您手机的当前时间不正确,请根据北京时间调整!";
				}
			}
		}
		return "非法请求,服务器已拦截!";
	}

	/** 根据传入字符串获得上传的路径 */
	public static String getUploadPath(HttpServletRequest request) {
		StringBuilder sb = new StringBuilder("http://");
		sb.append(request.getLocalAddr());
		sb.append(":");
		sb.append(request.getLocalPort());
		sb.append(request.getSession().getServletContext().getContextPath());
		sb.append("/resources/upload");
		return sb.toString();
	}

	/** 获得项目上传的路径 */
	public static String getUploadPath() {
		return BeanFactoryContext.getCtx() + "/resources/upload";
	}

	/**
	 * 设置Logo信息,flag=1为机构logo,flag=2为教师logo,flag=3为课程logo,flag=4为童星logo,flag=5
	 * 为用户logo,flag=6为家校通logo
	 */
	public static String getLogo(String logo, int flag) {
		String ctx = getUploadPath();
		if (EmptyUtil.isNotEmpty(logo)) {
			return ctx + "/logo/" + logo;
		} else {
			String path = ctx.substring(0, ctx.indexOf("/upload"));
			switch (flag) {
			case 1:
				return path + LOGO_PATH + PXJG_LOGO;
			case 2:
				return path + LOGO_PATH + TEACHER_LOGO;
			case 3:
				return path + LOGO_PATH + COURSE_LOGO;
			case 4:
				return path + LOGO_PATH + CHILDRENSTAR_LOGO;
			case 5:
				return path + LOGO_PATH + USER_LOGO;
			case 6:
				return path + LOGO_PATH + JXT_LOGO;
			default:
				return path + LOGO_PATH + PXJG_LOGO;
			}
		}
	}

	/**
	 * flag=1为机构logo,flag=2为教师logo,flag=3为课程logo,flag=4为童星logo,
	 * flag=5为用户logo,flag=6为课程类型logo
	 */
	public static String setLogo(String logo, int flag) {
		if (EmptyUtil.isNotEmpty(logo)) {
			switch (flag) {
			case 1:
				if (logo.indexOf(PXJG_LOGO) < 0) {
					return logo;
				}
				break;
			case 2:
				if (logo.indexOf(TEACHER_LOGO) < 0) {
					return logo;
				}
				break;
			case 3:
				if (logo.indexOf(COURSE_LOGO) < 0) {
					return logo;
				}
				break;
			case 4:
				if (logo.indexOf(CHILDRENSTAR_LOGO) < 0) {
					return logo;
				}
				break;
			case 5:
				if (logo.indexOf(USER_LOGO) < 0) {
					return logo;
				}
				break;
			case 6:
				if (logo.indexOf(COURSE_TYPE_LOGO) < 0) {
					return logo;
				}
				break;
			default:
				if (logo.indexOf(PXJG_LOGO) < 0) {
					return logo;
				}
				break;

			}
		}
		return null;
	}

	/**
	 * 计算当前位置与附近学校距离差是否小于半径
	 * 
	 * @param longitude1
	 * @param latitude1
	 * @param longitude2
	 * @param latitude2
	 * @param radius
	 * @return
	 */
	public static boolean isLessThanRadius(String longitude1, String latitude1, String longitude2, String latitude2, String radius) {
		double distance = getDoubleDistance(Double.valueOf(longitude1), Double.valueOf(latitude1), Double.valueOf(longitude2), Double.valueOf(latitude2));
		if (Math.abs(distance) <= Double.valueOf(radius))
			return true;
		else
			return false;
	}

	/**
	 * 计算当前位置与附近学校距离差是否小于半径
	 * 
	 * @param longitude1
	 * @param latitude1
	 * @param longitude2
	 * @param latitude2
	 * @param radius
	 * @return
	 */
	public static Double lessThanRadius(double longitude1, double latitude1, double longitude2, double latitude2, String radius) {
		double distance = getDoubleDistance(Double.valueOf(longitude1), Double.valueOf(latitude1), Double.valueOf(longitude2), Double.valueOf(latitude2));
		if (radius == null || EmptyUtil.isEmpty(radius)) {
			return Math.abs(distance);
		} else {
			if (Math.abs(distance) <= Double.valueOf(radius))
				return Math.abs(distance);
			else
				return null;
		}
	}

	/**
	 * 获取当前视野范围内的目标
	 * 
	 * @param leftBottom
	 * @param rightTop
	 * @param center
	 * @return
	 */
	public static Double lessThanBounds(Point leftBottom, Point rightTop, Point center, Point targetPoint) {
		if (isInBounds(targetPoint, leftBottom, rightTop)) {
			double distance = getDoubleDistance(Double.valueOf(targetPoint.getLongitude()), Double.valueOf(targetPoint.getLatitude()), Double.valueOf(center.getLongitude()), Double.valueOf(center.getLatitude()));
			return Math.abs(distance);
		}
		return null;
	}

	private static double rad(double d) {
		return d * Math.PI / 180.0;
	}

	/**
	 * 根据两点间经纬度坐标，计算两点间距离，单位为米
	 * 
	 * @param lng1
	 *            经度
	 * @param lat1
	 *            纬度
	 * @param lng2
	 *            经度
	 * @param lat2
	 *            纬度
	 * @return
	 */
	public static double getDoubleDistance(double lng1, double lat1, double lng2, double lat2) {
		double radLat1 = rad(lat1);
		double radLat2 = rad(lat2);
		double a = radLat1 - radLat2;
		double b = rad(lng1) - rad(lng2);
		double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
		s = s * EARTH_RADIUS;
		s = Math.round(s * 10000) / 10000;

		return s;
	}

	/**
	 * 根据两点间经纬度坐标，计算两点间距离，单位为米
	 * 
	 * @param lng1
	 *            经度
	 * @param lat1
	 *            纬度
	 * @param lng2
	 *            经度
	 * @param lat2
	 *            纬度
	 * @return
	 */
	public static String getStringDistance(double lng1, double lat1, double lng2, double lat2) {
		String distance = "";
		double radLat1 = rad(lat1);
		double radLat2 = rad(lat2);
		double a = radLat1 - radLat2;
		double b = rad(lng1) - rad(lng2);
		double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
		s = s * EARTH_RADIUS;
		s = Math.round(s * 10000) / 10000;
		DecimalFormat df = new DecimalFormat("######0.0");
		if (s < 500) {
			distance = s + "m";
		} else {
			distance = "<" + df.format(s / 1000) + "km";
		}
		return distance;
	}

	/**
	 * 判断目标经纬点是否在矩形范围内
	 * 
	 * @param targetPoint
	 * @param leftBottom
	 * @param rightTop
	 * @return
	 */
	public static boolean isInBounds(Point targetPoint, Point leftBottom, Point rightTop) {
		if (targetPoint.getLatitude() >= leftBottom.getLatitude() && targetPoint.getLongitude() >= leftBottom.getLongitude() && targetPoint.getLatitude() <= rightTop.getLatitude() && targetPoint.getLongitude() <= rightTop.getLongitude()) {
			return true;
		}
		return false;
	}

	/** 通过access_token得到openid （qq第三方登陆） */
	public static String getOpenId(String access_token) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("access_token", access_token);
		String openid = HttpTookit.doPost("https://graph.qq.com/oauth2.0/me", map);
		openid = openid.substring(openid.indexOf("(") + 2, openid.indexOf(")"));
		if (EmptyUtil.isNotEmpty(openid)) {
			JsonParser parser = new JsonParser();
			JsonElement el = parser.parse(openid);
			JsonObject jsonObj = null;
			if (el.isJsonObject()) {
				jsonObj = el.getAsJsonObject();
			}
			return jsonObj.get("openid").toString();
		} else {
			return null;
		}
	}

	/**
	 * 
	 * @param access_token
	 *            可通过使用Authorization_Code获取Access_Token 或来获取。
	 *            access_token有3个月有效期。
	 * @param oauth_consumer_key
	 *            申请QQ登录成功后，分配给应用的appid
	 * @param openid
	 *            用户的ID，与QQ号码一一对应。 可通过调用getOpenId()来获取。
	 * @return {@link <a href="http://wiki.connect.qq.com/get_user_info">返回参数声明</a>}
	 * 
	 */
	public static String getUserInfo(String access_token, String oauth_consumer_key, String openid) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("access_token", access_token);
		map.put("oauth_consumer_key", oauth_consumer_key);
		map.put("openid", openid);
		String user_info = HttpTookit.doPost("https://graph.qq.com/user/get_user_info", map);
		return user_info;
	}

	/**
	 * 权限自动续期
	 * 
	 * @param grant_type
	 *            授权类型，在本步骤中，此值为“refresh_token”。
	 * @param client_id
	 *            申请QQ登录成功后，分配给网站的appid。
	 * @param client_secret
	 *            申请QQ登录成功后，分配给网站的appkey。
	 * @param refresh_token
	 *            在授权自动续期步骤中，获取新的Access_Token时需要提供的参数。
	 * @return
	 */
	public static String renewalAccessToken(String grant_type, String client_id, String client_secret, String refresh_token) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("grant_type", grant_type);
		map.put("client_id", client_id);
		map.put("client_secret", client_secret);
		map.put("refresh_token", refresh_token);
		String result = HttpTookit.doPost("https://graph.qq.com/oauth2.0/token", map);
		return result;
	}

	/**
	 * 
	 * @param grant_type
	 *            授权类型，在本步骤中，此值为“authorization_code”。
	 * @param client_id
	 *            申请QQ登录成功后，分配给网站的appid。
	 * @param client_secret
	 *            申请QQ登录成功后，分配给网站的appkey。
	 * @param code
	 * @param redirect_uri
	 * @return
	 */
	public static String getAccessToken(String grant_type, String client_id, String client_secret, String code, String redirect_uri) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("grant_type", grant_type);
		map.put("client_id", client_id);
		map.put("client_secret", client_secret);
		map.put("code", code);
		map.put("redirect_uri", redirect_uri);
		String result = HttpTookit.doPost("https://graph.qq.com/oauth2.0/token", map);
		return result;

	}

	/**
	 * 
	 * @param response_type
	 *            (必须) 授权类型，此值固定为“code”。
	 * @param client_id
	 *            (必须) 申请QQ登录成功后，分配给应用的appid。
	 * @param redirect_uri
	 *            (必须) 成功授权后的回调地址，必须是注册appid时填写的主域名下的地址，建议设置为网站首页或网站的用户中心。
	 *            注意需要将url进行URLEncode。
	 * @param state
	 *            (必须) client端的状态值。用于第三方应用防止CSRF攻击，成功授权后回调时会原样带回。
	 *            请务必严格按照流程检查用户与state参数状态的绑定。
	 * @param scope
	 *            (可选 )请求用户授权时向用户显示的可进行授权的列表。
	 *            可填写的值是API文档中列出的接口，以及一些动作型的授权（目前仅有：do_like），如果要填写多个接口名称，请用逗号隔开。
	 *            例如：scope=get_user_info,list_album,upload_pic,do_like
	 *            不传则默认请求对接口get_user_info进行授权。
	 *            建议控制授权项的数量，只传入必要的接口名称，因为授权项越多，用户越可能拒绝进行任何授权。
	 * @param display
	 *            (可选 ) 仅PC网站接入时使用。 用于展示的样式。不传则默认展示为PC下的样式。
	 *            如果传入“mobile”，则展示为mobile端下的样式。
	 * 
	 * @param g_ut
	 *            (可选 ) 仅WAP网站接入时使用。 QQ登录页面版本（1：wml版本； 2：xhtml版本），默认值为1。
	 * 
	 * @return
	 */
	public static String getAuthorizationCode(String response_type, String client_id, String redirect_uri, String state, String scope, String display, String g_ut) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("response_type", response_type);
		map.put("client_id", client_id);
		map.put("redirect_uri", redirect_uri);
		map.put("state", state);
		map.put("scope", scope);
		map.put("display", display);
		map.put("g_ut", g_ut);
		String result = HttpTookit.doPost("https://graph.qq.com/oauth2.0/authorize", map);
		return result;
	}
}
